#pragma once
#include "Runtime/Utils/LockFreeList.h"
#include "Thread.h"
#include "Runtime/Utils/SmartPtr.h"

namespace Alice
{
	class RunnableTaskEvent;
	typedef SmartPtr<RunnableTaskEvent> RunnableTaskEventRef;
	typedef std::vector<RunnableTaskEventRef> RunnableTaskEventArray;
	class RunnableTaskEvent
	{
	public:
		static RunnableTaskEvent* CreateGraphEvent();
		bool AddSubsequent(class RunnableTask* Task)
		{
			return SubsequentList.PushIfNotClosed(Task);
		}
		void CheckDontCompleteUntilIsEmpty()
		{
		}
		void DontCompleteUntil(RunnableTaskEvent* EventToWaitFor)
		{
			new (EventsToWaitFor.data()) RunnableTaskEvent*(EventToWaitFor);
		}
		void DispatchSubsequents(ENamedThreads CurrentThreadIfKnown = ENamedThreads::AnyThread);
		void DispatchSubsequents(std::vector<RunnableTask*>& NewTasks, ENamedThreads CurrentThreadIfKnown = ENamedThreads::AnyThread);
		bool IsComplete() const
		{
			return SubsequentList.IsClosed();
		}
		void Wait(ENamedThreads CurrentThreadIfKnown = ENamedThreads::AnyThread);
	private:
		RunnableTaskEvent(bool bInInline = false) : ThreadToDoGatherOn(ENamedThreads::AnyHiPriThreadHiPriTask){}
		~RunnableTaskEvent() {}
	public:
		uint32 retain()
		{
			int32 RefCount = ReferenceCount.Increment();
			return RefCount;
		}
		uint32 release()
		{
			int32 RefCount = ReferenceCount.Decrement();
			if (RefCount == 0)
			{
				delete this;
			}
			return RefCount;
		}
	private:
		TClosableLockFreePointerListUnorderedSingleConsumer<RunnableTask, 0>				SubsequentList;
		RunnableTaskEventArray																EventsToWaitFor;
		ThreadSafeCounter																	ReferenceCount;
		ENamedThreads																		ThreadToDoGatherOn;
	};
}
